package com.example.zhu29.bledemo.activity;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.example.zhu29.bledemo.Contast;
import com.example.zhu29.bledemo.R;
import com.example.zhu29.bledemo.interFace.IBleConnectStatusListener;
import com.example.zhu29.bledemo.interFace.IBleIndicateListener;
import com.example.zhu29.bledemo.interFace.IBleWriteListener;
import com.example.zhu29.bledemo.util.ZBleManager;
import com.example.zhu29.bledemo.util.ZDataUtil;
import com.example.zhu29.bledemo.util.ZHexUtil;
import com.inuker.bluetooth.library.model.BleGattProfile;
import com.inuker.bluetooth.library.search.SearchResult;

import java.util.Arrays;

/**
 * Created by Administrator on 2017/12/12.
 * Blood pressure device bluetooth status
 */

public class SocketPressureActivity extends AppCompatActivity implements View.OnClickListener {

    private TextView tvContent;
    private TextView tvStart;
    private TextView tvStatus;
    private ProgressBar progress;
    private SearchResult mDevice;
    private String mType = "";
    private String mSnNumber;
    private View tvBeginPressure;
    private ZBleManager mBleManager;
    private int version_code = 2;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_socket_pressure);
        findID();
        getIntents();
        initScan();
        initListener();
    }

    private void initScan() {
        mBleManager = ZBleManager.getInstance();
        mBleManager.initBle(this);
    }

    private void initListener() {
        tvStart.setOnClickListener(this);
        tvBeginPressure.setOnClickListener(this);
    }

    private void connect() {
        mBleManager.connect(mDevice.getAddress(), new IBleConnectStatusListener() {
            @Override
            public void onStartConnect() {
                tvStatus.setText(R.string.start_connect);
                progress.setVisibility(View.VISIBLE);
            }

            @Override
            public void onConnectFail() {
                tvStatus.setText(R.string.connect_failed);
                progress.setVisibility(View.GONE);
            }

            @Override
            public void onConnectSuccess(int code, BleGattProfile data, String mac) {
                progress.setVisibility(View.GONE);
                tvStatus.setText(R.string.connect_success);

                write(mDevice.getAddress(), ZHexUtil.hexStringToBytes(ZDataUtil.getSendHex(0)));

                try {
                    Thread.sleep(1000L);
                    indicate();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onDisConnected(String mac) {
                tvStatus.setText(R.string.connect_cancel);
                progress.setVisibility(View.GONE);
            }
        });
    }

    /**
     * Send Write Data to Bluetooth
     * Send write data to bluetooth
     *
     * @param data Written byte data(The byte data that was written)
     */
    @SuppressLint("CheckResult")
    private void write(final String mac, final byte[] data) {
        mBleManager.write(mac, Contast.GATT_SERVICE_PRIMARY,
                Contast.CHARACTERISTIC_WRITEABLE, data, new IBleWriteListener() {
                    @Override
                    public void onWriteSuccess() {
                        Log.e("zdw", getString(R.string.write_data_ok) + Arrays.toString(data));
                    }

                    @Override
                    public void onWriteFailure(int code) {
                        Log.e("zdw", getString(R.string.write_data_error) + Arrays.toString(data));
                    }
                });
    }

    /**
     *
     * Subscribe to receive broadcast notifications
     */
    private void indicate() {
        mBleManager.indicate(mDevice.getAddress(), Contast.GATT_SERVICE_PRIMARY,
                Contast.CHARACTERISTIC_READABLE, new IBleIndicateListener() {
                    @Override
                    public void onIndicateSuccess() {
                        Log.e("zdw", getString(R.string.indicate_success));
                    }

                    @Override
                    public void onIndicateFailure(int code) {
                        Log.e("zdw", getString(R.string.indicate_failure));
                    }

                    @Override
                    public void onCharacteristicChanged(byte[] data) {
                        Log.e("zdw", getString(R.string.get_device_data) + Arrays.toString(data));
//                        getData(data);
                        if (data.length != 15 && data.length != 18)
                            getValueData2(data);
                    }
                });
    }

    @SuppressLint("StringFormatMatches")
    private void showContent(byte[] data) {
        if (data.length != 14) return;
        byte index2 = data[2];
        if (index2 != 3) return;//Get only result packages
        byte index9 = data[9];
        byte index10 = data[10];//9-10 Systolic blood pressure
        byte index11 = data[11];//diastolic pressure
        byte index12 = data[12];//heart rate
        tvContent.setText(String.format(getString(R.string.bp_result), index9 + index10, index11, index12));
    }

    /**
     * Here the processing results show that
     * The processing results are shown here
     */
    private void getData(byte[] data) {
        if (null == data) return;
        if ((data.length > 2 && data[2] == 3) || (data_temp.length > 2 && data_temp[2] == 3)) {
            if (data.length == 14) {
                showContent(data);
            } else {
                if (data_temp.length < 14) {
                    //If the total length is still insufficient, splice directly.
                    if (data_temp.length + data.length < 14) {
                        data_temp = byteMerger(data_temp, data);
                    }
                    //If that adds up to just enough length,
                    else if (data_temp.length + data.length == 14) {
                        data_temp = byteMerger(data_temp, data);
                        Log.e("zdw007", "length：" + length + "data_temp：" + Arrays.toString(data_temp));
                        showContent(data_temp);
                        data_temp = null;
                        data_temp = new byte[]{};
                    }
                }
            }

        }
    }


    private void getIntents() {
        Intent intent = getIntent();
        mDevice = intent.getParcelableExtra("device");
    }

    private void findID() {
        tvContent = findViewById(R.id.tv_content);
        tvStart = findViewById(R.id.tv_start);
        tvBeginPressure = findViewById(R.id.tv_start_pressure);
        tvStatus = findViewById(R.id.tv_status);
        progress = findViewById(R.id.progress);
    }

    //java Merge two byte arrays
    private byte[] byteMerger(byte[] byte_1, byte[] byte_2) {
        byte[] byte_3 = new byte[byte_1.length + byte_2.length];
        System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length);
        System.arraycopy(byte_2, 0, byte_3, byte_1.length, byte_2.length);
        return byte_3;
    }

    private String mHighValue, mmLowValue, mHeratValue;
    byte[] data_temp = new byte[]{};
    int length = 8;
    boolean flag = true;

    private void getValueData2(byte[] data) {
        if (null == data) return;

        //First decide whether it's a process package or a result package
        if (data_temp.length < 3) {
            data_temp = byteMerger(data_temp, data);
            if (data_temp.length > 2) {
                byte index2 = data_temp[2];
                //[85, 5, -18, 1, 75]
                switch (index2) {
                    case 2:
                        length = 8;
                        break;
                    case 3:
                        length = 14;
                        break;
                    case -18:
                        length = 5;
                        break;
                }
                //If that adds up to just enough length,
                if (data_temp.length == length) {
                    switch (length) {
                        case 8:
                            setPreValue(data_temp);
                            break;
                        case 14:
                            try {
                                byte[] valueArr = {data_temp[10], data_temp[9]};
                                String strValue = ZHexUtil.encodeHexStr(valueArr);//Glucose 10+9 is converting to decimal
                                mHighValue = String.valueOf(Integer.valueOf(strValue, 16));//high pressure
                                mmLowValue = String.valueOf(Integer.valueOf(ZHexUtil.encodeHexStr(new byte[]{data_temp[11]}), 16));//low pressure
                                mHeratValue = String.valueOf(Integer.valueOf(ZHexUtil.encodeHexStr(new byte[]{data_temp[12]}), 16));//low pressure

                                tvContent.setText(String.format(getString(R.string.bp_result), mHighValue, mmLowValue, mHeratValue));
                                if (flag)
                                    write(mDevice.getAddress(), ZHexUtil.hexStringToBytes(ZDataUtil.getSendHex(5)));
                                flag = false;
                            } catch (Exception e) {
                                Log.e("zdw007", e.toString());
                            }
                            break;
                        case 5:
//                            showHeadType(CONNECTSUCCESSTYPE);
//                            new CommonHintDialog(getContext()).title(getString(R.string.tip)).message(getString(R.string.bp_measure_error))
//                                    .builder().show();
                            break;
                    }
                    data_temp = null;
                    data_temp = new byte[]{};
                }
            }
        } else {
            if (data_temp.length < length) {
                //If the total length is still insufficient, splice directly.
                if (data_temp.length + data.length < length) {
                    data_temp = byteMerger(data_temp, data);
                }
                //If that adds up to just enough length,
                else if (data_temp.length + data.length == length) {
                    data_temp = byteMerger(data_temp, data);
                    Log.e("zdw007", "length：" + length + "data_temp：" + Arrays.toString(data_temp));
                    switch (length) {
                        case 8:
                            setPreValue(data_temp);
                            break;
                        case 14:
                            try {
                                byte[] valueArr = {data_temp[10], data_temp[9]};
                                String strValue = ZHexUtil.encodeHexStr(valueArr);//Glucose 10+9 is converting to decimal
                                mHighValue = String.valueOf(Integer.valueOf(strValue, 16));//high pressure
                                mmLowValue = String.valueOf(Integer.valueOf(ZHexUtil.encodeHexStr(new byte[]{data_temp[11]}), 16));//low pressure
                                mHeratValue = String.valueOf(Integer.valueOf(ZHexUtil.encodeHexStr(new byte[]{data_temp[12]}), 16));//low pressure

                                tvContent.setText(String.format(getString(R.string.bp_result), mHighValue, mmLowValue, mHeratValue));
                                if (flag)
                                    write(mDevice.getAddress(), ZHexUtil.hexStringToBytes(ZDataUtil.getSendHex(5)));
                                flag = false;
                            } catch (Exception e) {
                                Log.e("zdw007", e.toString());
                            }
                            break;
                        case 5:
                            Toast.makeText(this, R.string.error_hint, Toast.LENGTH_SHORT);
                            break;

                    }
                    data_temp = null;
                    data_temp = new byte[]{};
                }
                //If the total length exceeds, intercept it.
                else {
                    int excess_length = data_temp.length + data.length - length;
                    data_temp = byteMerger(data_temp, subBytes(data, 0, data.length - excess_length));
                    setPreValue(data_temp);
                    data_temp = subBytes(data, data.length - excess_length, excess_length);
                }
            }
        }
    }

    /**
     * Intercepting a specified length array in a byte array
     */
    public static byte[] subBytes(byte[] src, int begin, int count) {
        byte[] bs = new byte[count];
        System.arraycopy(src, begin, bs, 0, count);
        return bs;
    }

    /**
     * Get the process package displayed
     */
    private void setPreValue(byte[] data) {
        byte[] valueArr = {data[6], data[5]};
        try {
            String strValue = String.valueOf(Integer.valueOf(ZHexUtil.encodeHexStr(valueArr), 16));//Blood pressure 6 + 5 is converting to 10
            tvContent.setText(String.format(getString(R.string.process_value), strValue));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.tv_start:
                connect();
                break;
            case R.id.tv_start_pressure:
                write(mDevice.getAddress(), ZHexUtil.hexStringToBytes(ZDataUtil.getSendHex(1)));
                break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ZBleManager.getInstance().disConnectDevice(mDevice.getAddress());
        ZBleManager.getInstance().destroy(mDevice.getAddress());
    }
}
